/*
 * SoftwareSAR - 1.0
 */
package br.com.cpqd.ssar.gerenciador;

import com.sun.opengl.util.GLUT;
import java.awt.event.MouseWheelEvent;
import java.awt.event.MouseWheelListener;
import javax.media.opengl.GL;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLCanvas;
import javax.media.opengl.GLEventListener;
import javax.media.opengl.glu.GLU;

/**
 * Classe que faz a Renderização dos Eixos
 * @author Daniel Varanda
 */
public class RenderEixos implements GLEventListener{

    /**
     * GL
     */
    private GL gl;
    /**
     * GLU
     */
    private GLU glu = new GLU();
    /**
     * GLUT
     */
    private GLUT glut = new GLUT();
    /**
     * GLCanvas
     */
    private GLCanvas gLCanvas;

    //Listas Pré-Compiladas
    private int listaEixos;

    //Rotação e Translado
    private float rotacaoX = 0.0f;
    private float rotacaoY = 0.0f;
    private float rotacaoZ = 0.0f;
    private float posicaoX = 0.0f;
    private float posicaoY = 0.0f;
    private float posicaoZ = -12.0f;
    
    //Iluminação da cena
    private float[] luzAmbiente = {0.2f,0.2f,0.2f,1.0f};

    /**
     * Método Construtor
     * @param malhaGerada InterfaceRenderizacaoMalha
     * @param requisicaoServicos RequisicaoServicos
     * @param gLCanvas GLCanvas
     */
    public RenderEixos(GLCanvas gLCanvas) {
        super();
        this.gLCanvas = gLCanvas;
    }

    /**
    * Inicializa a Máquina de Estados
    * @param drawable GLAutoDrawable
    */
    public void init(GLAutoDrawable drawable) {
        // Obtem referência ao GL
        gl = drawable.getGL();
        // Especifica Cor de Fundo
        gl.glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
        // Pinta o Fundo da Tela com a Cor Escolhida
        gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
        // Habilita a definição da cor do material a partir da cor corrente
        gl.glEnable(GL.GL_COLOR_MATERIAL);
        // Habilita o depth-buffer
        gl.glEnable(GL.GL_DEPTH_TEST);
        // Habilita o modelo de colorização de Gouraud
        gl.glShadeModel(gl.GL_SMOOTH);

        //Habilita iluminação
        gl.glEnable(GL.GL_LIGHTING);
        gl.glEnable(GL.GL_LIGHT0);

        // Estabelece os parâmetros do modelo de iluminação ambiente
        gl.glLightModelfv(gl.GL_LIGHT_MODEL_AMBIENT, luzAmbiente, 0 );

        geraEixos();
    }

    public void display(GLAutoDrawable drawable) {
        gl = drawable.getGL();

        gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);

        gl.glMatrixMode(GL.GL_MODELVIEW);
        gl.glLoadIdentity();

        gl.glTranslatef(posicaoX, posicaoY, posicaoZ);

        gl.glRotatef(rotacaoX, 1.0f, 0.0f, 0.0f);
        gl.glRotatef(rotacaoY, 0.0f, 1.0f, 0.0f);
        gl.glRotatef(rotacaoZ, 0.0f, 0.0f, 1.0f);

        if (gl.glIsList(listaEixos)) {
            gl.glCallList(listaEixos);
        }
    }

    /**
     * Define a Janela de Visualização 2D (Inicializa)
     * @param autoDrawable GLAutoDrawable
     * @param x int
     * @param y int
     * @param width int
     * @param height int
     */
    public void reshape(GLAutoDrawable autoDrawable, int x, int y, int width, int height) {
        // Obtem referência ao GL
        gl = autoDrawable.getGL();
        // Evita divisão por zero
        if (height <= 0) {
            height = 1;
        }
        float h = (float) width / (float) height;
        gl.glViewport(0,0,width,height);
        // Seleciona matriz de projeção
        gl.glMatrixMode(GL.GL_PROJECTION);
        gl.glLoadIdentity();
        // Especifica a Projeção Perspectiva (angulo,aspecto,zMin,zMax))
        glu.gluPerspective(45.0f, h, 0.1, 2000.0);
        // Seleciona matriz do modelo
        gl.glMatrixMode(GL.GL_MODELVIEW);
        gl.glLoadIdentity();
    }

    public void displayChanged(GLAutoDrawable drawable, boolean modeChanged, boolean deviceChanged) {
    }

    /**
    * Gera os eixos
    */
    private void geraEixos(){
        listaEixos = gl.glGenLists(1);
        gl.glNewList(listaEixos,gl.GL_COMPILE);

        //Centro do eixo
        gl.glColor3f(1.0f, 0.0f, 0.0f);
        gl.glPushMatrix();
        gl.glTranslatef(0, 0, 0);
        glut.glutSolidSphere(0.5, 15, 15);
        gl.glPopMatrix();
        gl.glFlush();

        //Eixo X
        gl.glPushMatrix();
        gl.glTranslatef(0, 0, 0);
        gl.glRotatef(90, 0.0f, 1.0f, 0.0f);
        glut.glutSolidCylinder(0.2f, 2.5, 15, 15);
        gl.glPopMatrix();
        gl.glFlush();
        //Seta eixo X
        gl.glPushMatrix();
        gl.glTranslatef(2.5f, 0, 0);
        gl.glRotatef(90, 0.0f, 1.0f, 0.0f);
        glut.glutSolidCone(0.5f, 1, 15, 15);
        gl.glPopMatrix();
        gl.glFlush();
        //Letra X
        gl.glRasterPos3f(4f, 0.0f, -0.0f);
        glut.glutBitmapCharacter(GLUT.BITMAP_TIMES_ROMAN_10, 'X');

        //Eixo Y
        gl.glColor3f(0.0f, 1.0f, 0.0f);
        gl.glPushMatrix();
        gl.glTranslatef(0, 0, 0);
        gl.glRotatef(-90, 1.0f, 0.0f, 0.0f);
        glut.glutSolidCylinder(0.2f, 2.5, 15, 15);
        gl.glPopMatrix();
        gl.glFlush();
        //Seta eixo Y
        gl.glPushMatrix();
        gl.glTranslatef(0, 2.5f, 0);
        gl.glRotatef(-90, 1.0f, 0.0f, 0.0f);
        glut.glutSolidCone(0.5f, 1, 15, 15);
        gl.glPopMatrix();
        gl.glFlush();
        //Letra Y
        gl.glRasterPos3f(0.0f, 4f, -0.0f);
        glut.glutBitmapCharacter(GLUT.BITMAP_TIMES_ROMAN_10, 'Y');

        //Eixo Z
        gl.glColor3f(0.0f, 0.0f, 1.0f);
        gl.glPushMatrix();
        gl.glTranslatef(0, 0, 0);
        glut.glutSolidCylinder(0.2f, 2.5, 15, 15);
        gl.glPopMatrix();
        gl.glFlush();
        //Seta eixo Y
        gl.glPushMatrix();
        gl.glTranslatef(0, 0, 2.5f);
        glut.glutSolidCone(0.5f, 1, 15, 15);
        gl.glPopMatrix();
        gl.glFlush();
        //Letra Z
        gl.glRasterPos3f(-0.0f, 0.0f, 4f);
        glut.glutBitmapCharacter(GLUT.BITMAP_TIMES_ROMAN_10, 'Z');

        gl.glEndList();
    }

    public void setRotacao(float rotacaoX, float rotacaoY, float rotacaoZ){
        this.rotacaoX = rotacaoX;
        this.rotacaoY = rotacaoY;
        this.rotacaoZ = rotacaoZ;

        gLCanvas.display();
    }
}
